/********************************************************************
	created:	30:9:2007   16:12
	author:		tiamo
	purpose:	stdafx
*********************************************************************/

#pragma once

extern "C"
{
	#include <wdm.h>
	#include <kbdmou.h>
	#include <ntddkbd.h>
	#include <wmilib.h>
	#include <hidusage.h>
	#include <hidclass.h>
	#include <hidpi.h>
}

/// debug level
enum
{
	/// info
	DBGLEVEL_INFO														= 0x1,
	/// warning
	DBGLEVEL_WARNING													= 0x2,
	/// error
	DBGLEVEL_ERROR														= 0x4,
	/// none
	DBGLEVEL_NONE														= 0x8,
};

/// read state
enum
{
	READ_STATE_BEGIN													= 1,
	READ_STATE_END														= 2,
	READ_STATE_LOOPING													= 3,
};

/// usage mapping
struct CUsageMapping
{
	/// from
	USAGE_AND_PAGE														m_ulFrom;
	/// to
	USAGE_AND_PAGE														m_ulTo;
	/// next
	CUsageMapping*														m_pNextMapping;
};

/// hid data
struct CHidData
{
	/// preparsed data
	PHIDP_PREPARSED_DATA												m_pPreparsedData;
	/// caps
	HIDP_CAPS															m_hidCaps;
	/// max usage length
	ULONG																m_ulMaxUsageListLength;
	/// offset 48
	HIDP_KEYBOARD_MODIFIER_STATE										m_stateModifier;
	/// input report buffer
	PVOID																m_pInputReportBuffer;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pPrevInputUsageList;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pThisInputUsageList;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pChangedBreakUsageList;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pChangedMakeUsageList;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pMakeUsageList;
	/// usage list buffer
	PUSAGE_AND_PAGE														m_pBreakUsageList;
	/// input report buffer mdl
	PMDL																m_mdlInputReportBuffer;
};

/// device extension
struct CDeviceExtension
{
	/// fdo offset 0
	PDEVICE_OBJECT														m_pFunctionDeviceObject;
	/// lower device offset 4
	PDEVICE_OBJECT														m_pLowerDevice;
	/// pdo offset 8
	PDEVICE_OBJECT														m_pPhysicalDeviceObject;
	/// enable count offset c
	LONG																m_lEnableCount;
	/// ping-pong state offset 10
	LONG																m_lReadState;
	/// ping-pong stopped event offset 14
	KEVENT																m_eventPingPongStopped;
	/// read complete event offset 24
	KEVENT																m_eventReadComplete;
	/// started offset 34
	BOOLEAN																m_bDeviceStarted;
	/// offset 35
	BOOLEAN																m_bDeletePending;
	/// offset 36
	BOOLEAN																m_bLowerKeyboardDeviceStarted;
	/// offset 37
	UCHAR																m_ucPadding0;
	/// unit id offset 38
	USHORT																m_usUnitId;
	/// offset 3a - 40
	UCHAR																m_ucPadding1[6];
	/// irp offset 40
	PIRP																m_pReadIrp;
	/// hid data offset 44
	CHidData*															m_pHidData;
	/// problem flags
	ULONG																m_ulProblemFlags;
	/// read file offset 4c
	PFILE_OBJECT														m_pReadFileObject;
	/// connect data offset 50
	CONNECT_DATA														m_dataConnect;
	/// remove lock offset 58
	IO_REMOVE_LOCK														m_removeLock;
	/// fast mutex offset b0
	FAST_MUTEX															m_fastMutex;
	/// start device complete event
	KEVENT																m_eventStartComplete;
	/// input data offset e0
	KEYBOARD_INPUT_DATA													m_dataKeyboardInput;
	/// scancodes state offset ec
	ULONG																m_ulScanCodesState;
	/// keyboard attribute offset f0
	KEYBOARD_ATTRIBUTES													m_attributeKeyboard;
	/// wmi data offset 10c
	KEYBOARD_ID_EX														m_wmiKeyboardIdEx;
	/// indicator param offset 114
	KEYBOARD_INDICATOR_PARAMETERS										m_paramIndicator;
	///  typematic offset 118
	KEYBOARD_TYPEMATIC_PARAMETERS										m_paramTypematic;
	/// padding
	UCHAR																m_ucPadding2[2];
	/// auto repeat dpc offset 120
	KDPC																m_dpcAutoRepeat;
	/// repeat timer offset 140
	KTIMER																m_timerRepeat;
	/// repeat delay time offset 168
	LARGE_INTEGER														m_llTimeRepeatDelay;
	/// repeat period offset 170
	LONG																m_lRepeatPeriod;
	/// initi read dpc offset 174
	KDPC																m_dpcInitiateStartRead;
	/// offset 194
	UCHAR																m_ucPadding3[4];
	/// recover timer offset 198
	KTIMER																m_timerRecover;
	/// recover time offset 1c0
	LARGE_INTEGER														m_llTimeRecover;
	/// keyboard has problem offset 1c8
	LONG																m_bKeyboardProblem;
	/// padding offset 1cc
	UCHAR																m_ucPadding4[8];
	/// wmi lib context offset 1d4
	WMILIB_CONTEXT														m_wmiLibContext;
	/// usageid mappings offset 1f4
	CUsageMapping*														m_pUsageIdMappings;
	/// spinlock offset 1f8
	KSPIN_LOCK															m_spinLockUsageMappings;
	/// offset 1fc
	UCHAR																m_ucPadding5[4];
};

extern "C"
{
	/// driver entry
	NTSTATUS DriverEntry(__in PDRIVER_OBJECT pDriverObject,__in PUNICODE_STRING pRegPath);

	/// unload
	VOID AppleKeyboardUnload(__in PDRIVER_OBJECT pDriverObject);

	/// create complete
	NTSTATUS AppleKeyboardCreateComplete(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in PVOID pContext);

	/// create
	NTSTATUS AppleKeyboardCreate(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// close
	NTSTATUS AppleKeyboardClose(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// internal io control
	NTSTATUS AppleKeyboardInternalIoControl(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// io control
	NTSTATUS AppleKeyboardIoControl(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);


	/// set led indicator
	NTSTATUS AppleKeyboardSetLedIndicators(__in CDeviceExtension* pDevExt,__in PKEYBOARD_INDICATOR_PARAMETERS pParam,__in PIRP pIrp,
										   __in PIO_STACK_LOCATION pIrpSp);

	/// set led complete
	NTSTATUS AppleKeyboardSetLedIndicatorsComplete(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in PVOID pContext);

	/// start device complete
	NTSTATUS AppleKeyboardStartDeviceComplete(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in PVOID pContext);

	/// start device
	NTSTATUS AppleKeyboardStartDevice(__in CDeviceExtension* pDevExt);

	/// pnp
	NTSTATUS AppleKeyboardPnp(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// flush
	NTSTATUS AppleKeyboardFlush(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// power
	NTSTATUS AppleKeyboardPower(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// add device
	NTSTATUS AppleKeyboardAddDevice(__in PDRIVER_OBJECT pDriverObject,__in PDEVICE_OBJECT pPhysicalDeviceObject);

	/// debug break
	VOID AppleDbgBreakPoint();

	/// debug print
	VOID AppleDebugPrint(__in ULONG ulLevel,__in	PCCH pFormat,...);

	/// trace collection info
	VOID AppleTraceCollectionInfo(__in ULONG ulLevel,__in PHID_COLLECTION_INFORMATION pInfo);

	/// trace collection data
	VOID AppleTraceCollectionData(__in ULONG ulLevel,__in PVOID pDataBuffer,__in ULONG ulLength);

	/// trace caps
	VOID AppleTraceHidCaps(__in ULONG ulLevel,__in PHIDP_CAPS pCaps);

	/// insert codes
	BOOLEAN AppleKeyboardInsertCodesIntoQueue(__in PVOID pContext,__in PCHAR pNewScanCodes,__in ULONG ulLength);

	/// auto repeat
	VOID AppleKeyboardAutoRepeat(__in PKDPC pDpc,__in PVOID pDeferredContext,__in PVOID pSystemArgument1,__in PVOID pSystemArgument2);

	/// initiate start read
	VOID AppleKeyboardInitiateStartRead(__in PKDPC pDpc,__in PVOID pDeferredContext,__in PVOID pSystemArgument1,__in PVOID pSystemArgument2);

	/// read complete
	NTSTATUS AppleKeyboardReadComplete(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in PVOID pContext);

	/// start read
	NTSTATUS AppleKeyboardStartRead(__in CDeviceExtension* pDevExt);

	/// system control
	NTSTATUS AppleKeyboardSystemControl(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp);

	/// query wmi reg info
	NTSTATUS AppleKeyboardQueryWmiRegInfo(__in PDEVICE_OBJECT pDeviceObject,__out PULONG pulRegFlags,__out PUNICODE_STRING pInstanceName,
										  __out PUNICODE_STRING *ppRegistryPath,__out PUNICODE_STRING pMofResourceName,__out PDEVICE_OBJECT *ppPdo);


	/// query data block
	NTSTATUS AppleKeyboardQueryWmiDataBlock(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in ULONG ulGuidIndex,__in ULONG ulInstanceIndex,
											__in ULONG ulInstanceCount,__in __out PULONG pulInstanceLengthArray,__in ULONG ulBufferAvail,__out PUCHAR pBuffer);

	/// set data block
	NTSTATUS AppleKeyboardSetWmiDataBlock(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in ULONG ulGuidIndex,__in ULONG ulInstanceIndex,
										  __in ULONG ulBufferSize,__in PUCHAR pBuffer);

	/// set data item
	NTSTATUS AppleKeyboardSetWmiDataItem(__in PDEVICE_OBJECT pDeviceObject,__in PIRP pIrp,__in ULONG ulGuidIndex,__in ULONG ulInstanceIndex,
										 __in ULONG ulDataItemId,__in ULONG ulBufferSize,__in PUCHAR pBuffer);

	/// string to hex
	USAGE_AND_PAGE AppleKeyboardString2Hex(__in PWCH pString,__in ULONG ulLength);

	/// load usage list
	VOID AppleKeyboardLoadUsageMappingList(__in CDeviceExtension* pDevExt);

	/// map usage
	VOID AppleKeyboardMapUsage(__in CDeviceExtension* pDevExt,__in __out PUSAGE_AND_PAGE pUsageAndPage);

	/// free usageid mappings
	VOID AppleKeyboardFreeUsageMappingList(__in CDeviceExtension* pDevExt);

	/// call hid class
	NTSTATUS AppleKeyboardCallHidClass(__in CDeviceExtension* pDevExt,__in ULONG ulIoControlCode,__in PVOID pInputBuffer,__in ULONG ulInputLength,
									   __out PVOID pOutBuffer,__in ULONG ulOutputLength);

	/// query reg key
	NTSTATUS AppleKeyboardQueryDeviceKey(__in HANDLE hKey,__in PWCH pValueName,__in __out PVOID pDataBuffer,__in ULONG ulDataLength);

	/// update callback
	VOID AppleUpdateRegistryProblemFlagsCallback(__in PDEVICE_OBJECT pDeviceObject,__in_opt PVOID pContext);

	/// set problem flags
	VOID AppleUpdateRegistryProblemFlags(__in CDeviceExtension* pDevExt,__in PUSAGE_AND_PAGE pInputUsage);

	// tranlate to 8024scan codes
	NTSTATUS AppleKeyboardTranslateUsageAndPagesToI8042ScanCodes(__in PUSAGE_AND_PAGE pChangedUsageList,__in ULONG ulUsageListLength,
																 __in HIDP_KEYBOARD_DIRECTION keyAction,__in __out PHIDP_KEYBOARD_MODIFIER_STATE pModifierState,
																 __in PHIDP_INSERT_SCANCODES pInsertCodesProcedure,__in PVOID pInsertCodesContext);
}

/// guid list
extern WMIGUIDREGINFO													g_wmiGuidAppleKeyboard[2];
/// reg path
extern UNICODE_STRING													g_regPath;
